package com.yizhuoyan.his.serviceimpl.admin;

import com.yizhuoyan.his.ao.FinExpenseCategoryAo;
import com.yizhuoyan.his.dao.FinExpenseCategoryDao;
import com.yizhuoyan.his.entity.FinExpenseCategoryEntity;
import com.yizhuoyan.his.exception.HISDataExistsException;
import com.yizhuoyan.his.exception.HISIllegalParameterException;
import com.yizhuoyan.his.service.admin.FinanceExpenseCategoryManageService;
import com.yizhuoyan.his.servicesupport.DatabaseIdGenerateSupportService;
import com.yizhuoyan.his.util.AssertThrowUtil;
import com.yizhuoyan.his.util.BeanMap;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validator;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 财务收费类别管理服务
 */
@Service
@Validated
@Transactional
@Slf4j
public class FinanceExpenseCategoryManageServiceImpl implements FinanceExpenseCategoryManageService,AssertThrowUtil {

    @Autowired
    DatabaseIdGenerateSupportService idGenerateSupportService;

    @Autowired
    FinExpenseCategoryDao expenseCategoryDao;

    @Override
    public FinExpenseCategoryEntity addExpenseCategory(@NonNull  @Valid FinExpenseCategoryAo ao) throws Exception {
        log.trace("添加财务收费类别,参数为：{}",ao);
        String name=ao.getName();
        String code=ao.getCode();
        if(expenseCategoryDao.exists("code",code)){
            log.trace("财务收费类别代号{}已存在，不可以添加",code);
            throw new HISDataExistsException(String.format("代号[%s]已存在",code));
        }
        log.trace("财务收费类别代号{}不存在，可以添加",code);
        FinExpenseCategoryEntity e=new FinExpenseCategoryEntity();
        e.setCode(code);
        e.setName(name);
        e.setId(idGenerateSupportService.nextId());
        expenseCategoryDao.insert(e);
        log.trace("财务收费类别添加成功{}",ao);
        return e;
    }
    private void assertExpenseCategoryIdCorrect(@NonNull Long id){
        log.trace("判断id是否合法，目前仅判断是否>0");
        assertGreatThan("id",id,0);
    }

    @Override
    public void removeExpenseCategory( Long id) throws Exception {
        log.trace("删除财务收费类别，参数为{}",id);
        assertExpenseCategoryIdCorrect(id);
        log.trace("id[{}]合法，查找对应记录",id);
        FinExpenseCategoryEntity e = expenseCategoryDao.selectById(id);
        if(e==null){
            log.trace("未找到id[{}]对应记录，什么都不做，结束方法执行",id);
            return;
        }
        log.trace("判断类别id{}是否还在使用",id);
        //TODO 如何判断财务收费类别是否正在使用呢？

        log.trace("财务收费类别id{}未使用，执行删除",id);
        expenseCategoryDao.delete(id);
        log.trace("财务收费类别id{}执行删除成功",id);
    }

    @Override
    public void modifyExpenseCategory(Long id,@NonNull @Valid FinExpenseCategoryAo ao) throws Exception {
        assertExpenseCategoryIdCorrect(id);
        log.trace("id[{}]合法，查找对应记录",id);
        FinExpenseCategoryEntity e = expenseCategoryDao.selectById(id);
        assertNotNull("记录不存在或已被删除",e);

        BeanMap updateMap=BeanMap.of(3);
        String newCode=ao.getCode();
        log.trace("判断code是否需要修改");
        if(!Objects.equals(newCode,e.getCode())){
            log.trace("code需要修改,判断新code是否已存在");
            if(expenseCategoryDao.exists("code",newCode)){
                log.trace("财务收费类别代号{}已存在，不可以添加",newCode);
                throw new HISDataExistsException(String.format("代号[%s]已存在",newCode));
            }
            log.trace("newCode合法，需要修改");
            updateMap.append("code",newCode);
        }
        log.trace("判断name是否需要修改");
        String newName=ao.getName();
        if(!Objects.equals(newName,e.getName())){
            log.trace("newName合法，需要修改");
            updateMap.append("name",newName);
        }

        if(!updateMap.isEmpty()){
            log.trace("执行更新，需要修改字段为{}",updateMap);
            expenseCategoryDao.update(id,updateMap);
        }
    }

    @Override
    public FinExpenseCategoryEntity queryExpenseCategory(Long id) throws Exception {
        assertExpenseCategoryIdCorrect(id);
        log.trace("id[{}]合法，查找对应记录",id);
        FinExpenseCategoryEntity e = expenseCategoryDao.selectById(id);
        if(e==null){
            log.trace("未找到id[{}]对应记录直接返回null",id);
            return null;
        }
        return e;
    }

    @Override
    public List<FinExpenseCategoryEntity> queryExpenseCategoriesByKey(String key) throws Exception {
        log.debug("模糊查询财务收费类别，key为：{}",key);

        if(key!=null){
            final int keyMaxChars=10;
            log.trace("判断查询关键字是否超过{}个字符长度",keyMaxChars);
            assertLessThan("查询关键字",key,keyMaxChars);
            key=key+"%";
        }
        List<FinExpenseCategoryEntity> result = expenseCategoryDao.selectByKeyWithPagination(key, 1, Integer.MAX_VALUE);
        return result;
    }

    @Autowired
    Validator validator;
    @Override
    public void validateExpenseCategoryCodeValid(@NonNull String code) throws Exception {
        log.debug("验证财务收费类别code[{}]是否可用",code);

        log.trace("判断code[{}]格式是否合法",code);
        Set<ConstraintViolation<FinExpenseCategoryAo>> validateResult = validator.validateValue(FinExpenseCategoryAo.class, "code", code);
        if(!validateResult.isEmpty()){
            for (ConstraintViolation<FinExpenseCategoryAo> cv:validateResult){
                throw new HISIllegalParameterException(cv.getMessage());
            }
        }
        log.trace("判断code[{}]是否已存在",code);
        if(expenseCategoryDao.exists("code",code)){
            throw new HISDataExistsException(String.format("代号[%s]已存在",code));
        }

    }
}

